package main.leetcode.clockin.September;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.PriorityQueue;

/**
 * 347. 前 K 个高频元素
 *
 * <p>给定一个非空的整数数组，返回其中出现频率前 k 高的元素。
 *
 * <p>示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
 *
 * <p>示例 2: 输入: nums = [1], k = 1 输出: [1]
 *
 * <p>提示：你可以假设给定的 k 总是合理的，且 1 ≤ k ≤ 数组中不相同的元素的个数。 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
 * 题目数据保证答案唯一，换句话说，数组中前 k 个高频元素的集合是唯一的。 你可以按任意顺序返回答案。
 */
public class day7 {
    public static void main(String[] args) {
        System.out.println(
                Arrays.toString(new day7().topKFrequent(new int[] {1, 1, 1, 2, 2, 3}, 2)));
        System.out.println(Arrays.toString(new day7().topKFrequent(new int[] {3, 0, 1, 0}, 1)));
    }

    public int[] topKFrequent(int[] nums, int k) {
        int[] res = new int[k];
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        PriorityQueue<Node> heap = new PriorityQueue<>(Comparator.comparingInt(o -> o.cnt));
        for (Integer num : map.keySet()) {
            int cnt = map.get(num);
            if (heap.size() == k && heap.peek().cnt < cnt) {
                heap.poll();
                heap.offer(new Node(num, cnt));
            } else if (heap.size() < k) {
                heap.offer(new Node(num, map.get(num)));
            }
        }
        int index = 0;
        for (Node node : heap) {
            res[index++] = node.val;
        }
        return res;
    }

    private static class Node {
        private int val;
        private int cnt;

        public Node(int val, int cnt) {
            this.val = val;
            this.cnt = cnt;
        }
    }
}
